{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "<table>\n",
    " <tr align=left><td><img align=left src=\"./images/CC-BY.png\">\n",
    " <td>Text provided under a Creative Commons Attribution license, CC-BY. All code is made available under the FSF-approved MIT license. (c) Kyle T. Mandli</td>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "outputs": [],
   "source": [
    "from __future__ import print_function"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Plotting with `matplotlib`\n",
    "\n",
    "The most common facility for plotting with the Python numerical suite is to use the `matplotlib` package.  We will cover a few of the basic approaches to plotting figures.  If you are interested in learning more about `matplotlib` or are looking to see how you might create a particular plot check out the matplotlib [gallery](http://matplotlib.org/gallery) for inspiration.\n",
    "\n",
    "Please see the [matplotlib](https://matplotlib.org) site for more details and examples."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Interfaces\n",
    "\n",
    "There are two primary ways to interface with the plotting facilities in `matplotlib`\n",
    " - Influenced by `MATLAB`, a procedural interface and\n",
    " - An object oriented interface"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "#%matplotlib notebook\n",
    "import numpy\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "These commands import the necessary functions for NumPy and `matplotlib` for our demos.  The first command is so that the IPython notebook will make our plots and display them in the notebook."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Matlab Inspired Interface\n",
    "First off, lets plot a simple quadratic function $f(x) = x^2 + 2x + 3$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "x = numpy.linspace(-5, 5, 100)\n",
    "#print(x)\n",
    "y = x**2 + 2 * x + 3\n",
    "#print(y)\n",
    "plt.plot(x, y, 'ro')\n",
    "# plt.plot?\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "We can also label our plot (please do this), set the bounds and change the style of the plot:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "plt.plot(x, y, 'r--')\n",
    "plt.xlabel(\"time (s)\")\n",
    "plt.ylabel(\"Tribble Population\")\n",
    "plt.title(\"Tribble Growth\")\n",
    "plt.xlim([0, 4])\n",
    "plt.ylim([0, 25])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "It is possible to include the graph of more than one relationship. Simply use additional plot commands for each relationship you wish to graph. When doing so it is polite to include a legend. \n",
    "\n",
    "More information about using the [legend command](https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.legend.html) is available at the matplotlib website."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "y1 = x\n",
    "plt.plot(x,x,'g',label='Linear')\n",
    "plt.plot(x,x*x,'r',label='Quadratic')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "The other major way to plot data is via a pseudo-color plot.  A pseudo-color plot takes 3-dimensional data (or 2-dimensional depending on how you look at it) and plots it using color to represent the values of the function.  Say we have a function $f(x, y)$, we can plot a pseudo-color by using the following commands."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "x = numpy.linspace(-1, 1, 100)\n",
    "y = numpy.linspace(-1, 1, 100)\n",
    "X, Y = numpy.meshgrid(x, y)\n",
    "F = numpy.sin(X**2) + numpy.cos(Y**2)\n",
    "plt.pcolor(X, Y, F)\n",
    "plt.colorbar(label=\"stuff\")\n",
    "plt.title('Pseudo-Color plot')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "instead of pcolor,  you could also make a filled contour plot using contourf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "plt.contourf(X, Y, F)\n",
    "plt.colorbar(label=\"stuff\")\n",
    "plt.title('Contour Plot')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "Here we have used a new way to create NumPy `ndarray`s so that we can easily evaluate 2-dimensional functions.  The function `meshgrid` takes two 1-dimensional arrays and turns them into 2, 2-dimensional arrays whose matching indices will provide an easy to use set of arrays that can be evaluate 2-dimensional functions.\n",
    "\n",
    "In the current version of Matplotlib (v3.x), the default colormap is 'viridis' while earlier versions used a rainbow colormap known as 'jet'.  I highly suggest looking at [this explanation of how to choose a colormap](http://matplotlib.org/users/colormaps.html) if you are interested.  \n",
    "\n",
    "Anyway, let us make this plot also more useful."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "color_map = plt.get_cmap(\"Oranges\")\n",
    "plt.gcf().set_figwidth(plt.gcf().get_figwidth() * 2) \n",
    "plt.subplot(1, 2, 1, aspect=\"equal\")\n",
    "plt.pcolor(X, Y, F, cmap=color_map)\n",
    "plt.colorbar(label=\"Density\")\n",
    "\n",
    "plt.xlabel(\"x (m)\")\n",
    "plt.ylabel(\"y (m)\")\n",
    "plt.title(\"Tribble Density ($Number/m^2$)\")\n",
    "\n",
    "plt.subplot(1, 2, 2, aspect=\"equal\")\n",
    "plt.pcolor(X, Y, X*Y, cmap=plt.get_cmap(\"RdBu\"))\n",
    "plt.xlabel(\"x (m)\")\n",
    "plt.ylabel(\"y (m)\")\n",
    "plt.title(\"Tribble Birth Rate Anomaly\")\n",
    "plt.colorbar(label=\"Birth Rate Deviation\")\n",
    "\n",
    "plt.autoscale(enable=True, tight=False)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Object-Oriented Interface\n",
    "\n",
    "A much better way to \"build\" plots is to use a more object-oriented approach.  In this case, we create the objects and manipulate them which allows us to have more control over how we create plots.  Here we will create the annotated plots so that we have examples on how to do the same things (notice that they are very similar).  The basic premise of this approach is that you generate objects that can be manipulated and remain persistent."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "x = numpy.linspace(-5, 5, 100)\n",
    "\n",
    "fig = plt.figure()\n",
    "axes = fig.add_subplot(1, 1, 1)\n",
    "growth_curve = axes.plot(x, x**2 + 2 * x + 3, 'r--')\n",
    "axes.set_xlabel(\"time (s)\")\n",
    "axes.set_ylabel(\"Tribble Population\")\n",
    "axes.set_title(\"Tribble Growth\")\n",
    "axes.set_xlim([0, 4])\n",
    "axes.set_ylim([0, 25])\n",
    "#growth_curve[0].set_color('b')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "Here is the other example with a few extra tricks added in."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "x = numpy.linspace(-1, 1, 100)\n",
    "y = numpy.linspace(-1, 1, 100)\n",
    "X, Y = numpy.meshgrid(x, y)\n",
    "\n",
    "fig = plt.figure()\n",
    "fig.set_figwidth(fig.get_figwidth() * 2)\n",
    "\n",
    "axes = fig.add_subplot(1, 2, 1, aspect='equal')\n",
    "tribble_density = axes.pcolor(X, Y, numpy.sin(X**2) + numpy.cos(Y**2), cmap=plt.get_cmap(\"Oranges\"))\n",
    "axes.set_xlabel(\"x (km)\")\n",
    "axes.set_ylabel(\"y (km)\")\n",
    "axes.set_title(\"Tribble Density ($N/km^2$)\")\n",
    "cbar = fig.colorbar(tribble_density, ax=axes)\n",
    "cbar.set_label(\"$1/km^2$\")\n",
    "\n",
    "axes = fig.add_subplot(1, 2, 2, aspect='equal')\n",
    "klingon_population_density = axes.pcolor(X, Y, X * Y + 1, cmap=plt.get_cmap(\"RdBu\"))\n",
    "axes.set_xlabel(\"x (km)\")\n",
    "axes.set_ylabel(\"y (km)\")\n",
    "axes.set_title(\"Tribble Birth Rate Anomaly\")\n",
    "cbar = fig.colorbar(klingon_population_density, ax=axes)\n",
    "cbar.set_label(\"Birth Rate Deviation\")\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Make sure to visit ([matplotlib.org](https://matplotlib.org/)) for all sorts of other hints, tricks, and documentation."
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  },
  "latex_envs": {
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 0
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
